# For this task, you’ll likely need to use statistical software such as R, SAS, or Python.
#
# Using the same transaction dataset, identify the annual salary for each customer
#
# Explore correlations between annual salary and various customer attributes (e.g. age). These attributes could be those that are readily available in the data (e.g. age) or those that you construct or derive yourself (e.g. those relating to purchasing behaviour). Visualise any interesting correlations using a scatter plot.
#
# Build a simple regression model to predict the annual salary for each customer using the attributes you identified above
#
# How accurate is your model? Should ANZ use it to segment customers (for whom it does not have this data) into income brackets for reporting purposes?
#
# For a challenge: build a decision-tree based model to predict salary. Does it perform better? How would you accurately test the performance of this model?
options(max.print=1000000)
library(readxl)
library(dplyr)
fileName_task2 <- "ANZ synthesised transaction dataset.xlsx"
df_task2 <- as.data.frame(read_xlsx(fileName_task2))
Expecting numeric in C3052 / R3052C3: got 'THE DISCOUNT CHEMIST GROUP'Expecting numeric in C4360 / R4360C3: got 'LAND WATER & PLANNING East Melbourne'
df_task2
library(ggplot2)
### Annual Salary of each customer ###
salary <- data.frame()
salary <- subset(df_task2, df_task2$txn_description=='PAY/SALARY')
salary <- salary[, c('first_name', 'txn_description', 'amount', 'account')]
salary_sum <- data.frame()
salary_sum <- aggregate(salary$amount, list(factor(salary$account)), sum)
names_account_ids <- data.frame()
names_account_ids <- salary[c('first_name', 'account', 'amount')]
names_account_ids_arrange <- data.frame()
names_account_ids_arrange <- arrange(names_account_ids, list(factor(names_account_ids$account)))
sum_of_salaries <- data.frame()
sum_of_salaries <- aggregate(names_account_ids_arrange$amount, list(factor(names_account_ids_arrange$account) ), sum)
{
png(filename="Salary.png", width=1350, height=600)
### ggplot init
plt <- ggplot(sum_of_salaries, aes(Group.1, x, group=1))
### Labels
l <- labs(x="Accounts", y="Total Salary", title="Salaries drawn by customers")
### theme start
t<- theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size=12, face="bold", colour = "blue"),
plot.title = element_text(size=16, face= "bold", colour= "brown" ),
axis.title.x = element_text(size=14, face="bold", colour = "orange"),
axis.title.y = element_text(size=14, face="bold", colour = "orange"),
#axis.text.x = element_text(size=12, face="bold", colour = "black"),
axis.text.y = element_text(size=12, face="bold", colour = "blue"))
###theme end
print(plt+geom_point(size=4, col="red")+l+t)
dev.off()
}
null device
1
print(plt+geom_point(size=4, col="red")+l+t)

library(ggplot2)
library(ggrepel)
### Annual Salary of each customer ###
salary1 <- data.frame()
salary1 <- subset(df_task2, df_task2$txn_description=='PAY/SALARY')
salary1 <- salary1[, c('first_name', 'txn_description', 'amount', 'account', 'age')]
salary_sum1 <- data.frame()
salary_sum1 <- aggregate(salary1$amount, list(factor(salary1$account)), sum)
names_account_ids1 <- data.frame()
names_account_ids1 <- salary1[c('first_name', 'account', 'amount', 'age')]
names_account_ids_arrange1 <- data.frame()
names_account_ids_arrange1 <- arrange(names_account_ids1, list(factor(names_account_ids1$account)))
names_account_ids_arrange1 <- arrange(names_account_ids_arrange1, list(factor(names_account_ids_arrange1$account)))
sum_of_salaries1 <- data.frame()
sum_of_salaries1 <- aggregate(names_account_ids_arrange1$amount, list(factor(names_account_ids_arrange1$account) ), sum)
age_wise <- data.frame()
age_wise <- with(names_account_ids_arrange1, names_account_ids_arrange1[order(age, amount),])
age_wise <- aggregate(age_wise$amount, list(factor(names_account_ids_arrange1$age)), sum)
ageNum <- table(df_task2$age)
ageNum_vector <- c()
for (i in seq_along(1:length(ageNum))){
ageNum_vector <- append(ageNum_vector, ageNum[[i]])
}
age_wise$'age_num' <- ageNum_vector
{
png(filename="Salary_age_wise.png", width=1200, height=500)
### ggplot init
plt <- ggplot(age_wise, aes(Group.1, x))
### Labels
l <- labs(x="Age", y="Total Salary", title="Salaries Age Wise")
### theme start
t<- theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size=12, face="bold", colour = "blue"),
plot.title = element_text(size=16, face= "bold", colour= "brown" ),
axis.title.x = element_text(size=14, face="bold", colour = "orange"),
axis.title.y = element_text(size=14, face="bold", colour = "orange"),
#axis.text.x = element_text(size=12, face="bold", colour = "black"),
axis.text.y = element_text(size=12, face="bold", colour = "blue"))
###theme end
print(plt+geom_point(size=6, show.legend = TRUE)+l+t + geom_label_repel(aes(label = age_wise$age_num),
box.padding = 1,
label.size = 0.5,
point.padding = 0.5,
segment.color = 'blue') + geom_hline(yintercept=mean(age_wise$x), show.legend = TRUE, colour='green', size=1.5))
dev.off()
}
null device
1
#### Plot of first 30 Observations ###########
{
png(filename="Sum_Age_Individual.png", width=1400, height=600)
sum_age_individual <- aggregate(names_account_ids_arrange1$amount, list(factor(names_account_ids_arrange1$account), factor(names_account_ids_arrange1$age) ), sum)
tt<- theme(axis.ticks.x = element_blank(),
axis.text.x = element_blank(), plot.title = element_text(size=16, face= "bold", colour= "brown"), strip.text = element_text(size = 20, color = "dark green"),
axis.title.x = element_text(size=14, face="bold", colour = "orange"),
axis.title.y = element_text(size=14, face="bold", colour = "orange"),
#axis.text.x = element_text(size=12, face="bold", colour = "black"),
axis.text.y = element_text(size=12, face="bold", colour = "blue"))
lA <- labs(x="Accounts", y="Total Salary", title="Salaries by Individual Age")
plt_A <- ggplot(sum_age_individual[1:46, ], aes(Group.1, x, group=Group.2))
plt_A1 <- plt_A + facet_grid(. ~ Group.2) + geom_point(size=2.5, col='red') +lA + tt
print(plt_A1)
dev.off()
}
null device
1
#### Plot of first 31-60 Observations ###########
{
png(filename="Sum_Age_Individual1.png", width=1200, height=600)
lB <- labs(x="Accounts", y="Total Salary", title="Salaries by Individual Age")
plt_B <- ggplot(sum_age_individual[47:73, ], aes(Group.1, x, group=Group.2))
plt_B1 <- plt_B + facet_grid(. ~ Group.2) + geom_point(size=2.5, col='red') + lB + tt
print(plt_B1)
dev.off()
}
null device
1
#### Plot of first 61-100 Observations ###########
{
png(filename="Sum_Age_Individual2.png", width=1200, height=600)
lC <- labs(x="Accounts", y="Total Salary", title="Salaries by Individual Age")
plt_C <- ggplot(sum_age_individual[74:100, ], aes(Group.1, x, group=Group.2))
plt_C1 <- plt_C + facet_grid(. ~ Group.2) + geom_point(size=2.5, col='red') + lC + tt
print(plt_C1)
dev.off()
}
null device
1
confusionMatrix(predictions, data.frame(Group.1=53))
Error: `data` and `reference` should be factors with the same levels.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIA0KDQpgYGB7cn0NCg0KIyBGb3IgdGhpcyB0YXNrLCB5b3XigJlsbCBsaWtlbHkgbmVlZCB0byB1c2Ugc3RhdGlzdGljYWwgc29mdHdhcmUgc3VjaCBhcyBSLCBTQVMsIG9yIFB5dGhvbi4NCiMgDQojIFVzaW5nIHRoZSBzYW1lIHRyYW5zYWN0aW9uIGRhdGFzZXQsIGlkZW50aWZ5IHRoZSBhbm51YWwgc2FsYXJ5IGZvciBlYWNoIGN1c3RvbWVyDQojIA0KIyBFeHBsb3JlIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIGFubnVhbCBzYWxhcnkgYW5kIHZhcmlvdXMgY3VzdG9tZXIgYXR0cmlidXRlcyAoZS5nLiBhZ2UpLiBUaGVzZSBhdHRyaWJ1dGVzIGNvdWxkIGJlIHRob3NlIHRoYXQgYXJlIHJlYWRpbHkgYXZhaWxhYmxlIGluIHRoZSBkYXRhIChlLmcuIGFnZSkgb3IgdGhvc2UgdGhhdCB5b3UgY29uc3RydWN0IG9yIGRlcml2ZSB5b3Vyc2VsZiAoZS5nLiB0aG9zZSByZWxhdGluZyB0byBwdXJjaGFzaW5nIGJlaGF2aW91cikuIFZpc3VhbGlzZSBhbnkgaW50ZXJlc3RpbmcgY29ycmVsYXRpb25zIHVzaW5nIGEgc2NhdHRlciBwbG90Lg0KIyANCiMgQnVpbGQgYSBzaW1wbGUgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IHRoZSBhbm51YWwgc2FsYXJ5IGZvciBlYWNoIGN1c3RvbWVyIHVzaW5nIHRoZSBhdHRyaWJ1dGVzIHlvdSBpZGVudGlmaWVkIGFib3ZlDQojIA0KIyBIb3cgYWNjdXJhdGUgaXMgeW91ciBtb2RlbD8gU2hvdWxkIEFOWiB1c2UgaXQgdG8gc2VnbWVudCBjdXN0b21lcnMgKGZvciB3aG9tIGl0IGRvZXMgbm90IGhhdmUgdGhpcyBkYXRhKSBpbnRvIGluY29tZSBicmFja2V0cyBmb3IgcmVwb3J0aW5nIHB1cnBvc2VzPw0KIyANCiMgRm9yIGEgY2hhbGxlbmdlOiBidWlsZCBhIGRlY2lzaW9uLXRyZWUgYmFzZWQgbW9kZWwgdG8gcHJlZGljdCBzYWxhcnkuIERvZXMgaXQgcGVyZm9ybSBiZXR0ZXI/IEhvdyB3b3VsZCB5b3UgYWNjdXJhdGVseSB0ZXN0IHRoZSBwZXJmb3JtYW5jZSBvZiB0aGlzIG1vZGVsPw0KDQoNCm9wdGlvbnMobWF4LnByaW50PTEwMDAwMDApDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoZHBseXIpDQpmaWxlTmFtZV90YXNrMiA8LSAiQU5aIHN5bnRoZXNpc2VkIHRyYW5zYWN0aW9uIGRhdGFzZXQueGxzeCINCmRmX3Rhc2syIDwtIGFzLmRhdGEuZnJhbWUocmVhZF94bHN4KGZpbGVOYW1lX3Rhc2syKSkNCmRmX3Rhc2syDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQojIyMgQW5udWFsIFNhbGFyeSBvZiBlYWNoIGN1c3RvbWVyICMjIw0Kc2FsYXJ5IDwtIGRhdGEuZnJhbWUoKQ0Kc2FsYXJ5IDwtIHN1YnNldChkZl90YXNrMiwgZGZfdGFzazIkdHhuX2Rlc2NyaXB0aW9uPT0nUEFZL1NBTEFSWScpDQpzYWxhcnkgPC0gc2FsYXJ5WywgYygnZmlyc3RfbmFtZScsICd0eG5fZGVzY3JpcHRpb24nLCAnYW1vdW50JywgJ2FjY291bnQnKV0NCnNhbGFyeV9zdW0gPC0gZGF0YS5mcmFtZSgpDQpzYWxhcnlfc3VtIDwtIGFnZ3JlZ2F0ZShzYWxhcnkkYW1vdW50LCBsaXN0KGZhY3RvcihzYWxhcnkkYWNjb3VudCkpLCBzdW0pDQpuYW1lc19hY2NvdW50X2lkcyA8LSBkYXRhLmZyYW1lKCkNCm5hbWVzX2FjY291bnRfaWRzIDwtIHNhbGFyeVtjKCdmaXJzdF9uYW1lJywgJ2FjY291bnQnLCAnYW1vdW50JyldDQpuYW1lc19hY2NvdW50X2lkc19hcnJhbmdlIDwtIGRhdGEuZnJhbWUoKQ0KbmFtZXNfYWNjb3VudF9pZHNfYXJyYW5nZSA8LSBhcnJhbmdlKG5hbWVzX2FjY291bnRfaWRzLCBsaXN0KGZhY3RvcihuYW1lc19hY2NvdW50X2lkcyRhY2NvdW50KSkpDQpzdW1fb2Zfc2FsYXJpZXMgPC0gZGF0YS5mcmFtZSgpDQpzdW1fb2Zfc2FsYXJpZXMgPC0gYWdncmVnYXRlKG5hbWVzX2FjY291bnRfaWRzX2FycmFuZ2UkYW1vdW50LCBsaXN0KGZhY3RvcihuYW1lc19hY2NvdW50X2lkc19hcnJhbmdlJGFjY291bnQpICksIHN1bSkNCg0Kew0KICBwbmcoZmlsZW5hbWU9IlNhbGFyeS5wbmciLCB3aWR0aD0xMzUwLCBoZWlnaHQ9NjAwKQ0KICANCiAgIyMjIGdncGxvdCBpbml0DQogIA0KICBwbHQgPC0gZ2dwbG90KHN1bV9vZl9zYWxhcmllcywgYWVzKEdyb3VwLjEsIHgsIGdyb3VwPTEpKQ0KICANCiAgIyMjIExhYmVscw0KICANCiAgbCA8LSBsYWJzKHg9IkFjY291bnRzIiwgeT0iVG90YWwgU2FsYXJ5IiwgdGl0bGU9IlNhbGFyaWVzIGRyYXduIGJ5IGN1c3RvbWVycyIpDQogIA0KICAjIyMgdGhlbWUgc3RhcnQNCiAgDQogIHQ8LSB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSwgc2l6ZT0xMiwgZmFjZT0iYm9sZCIsIGNvbG91ciA9ICJibHVlIiksIA0KICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBmYWNlPSAiYm9sZCIsIGNvbG91cj0gImJyb3duIiApLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBmYWNlPSJib2xkIiwgY29sb3VyID0gIm9yYW5nZSIpLCAgICANCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0iYm9sZCIsIGNvbG91ciA9ICJvcmFuZ2UiKSwgICAgDQogICAgI2F4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGZhY2U9ImJvbGQiLCBjb2xvdXIgPSAiYmxhY2siKSwgDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgZmFjZT0iYm9sZCIsIGNvbG91ciA9ICJibHVlIikpIA0KICANCiAgIyMjdGhlbWUgZW5kDQogIA0KICBwcmludChwbHQrZ2VvbV9wb2ludChzaXplPTQsIGNvbD0icmVkIikrbCt0KQ0KICBkZXYub2ZmKCkNCn0NCnByaW50KHBsdCtnZW9tX3BvaW50KHNpemU9NCwgY29sPSJyZWQiKStsK3QpDQoNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncmVwZWwpDQojIyMgQW5udWFsIFNhbGFyeSBvZiBlYWNoIGN1c3RvbWVyICMjIw0Kc2FsYXJ5MSA8LSBkYXRhLmZyYW1lKCkNCnNhbGFyeTEgPC0gc3Vic2V0KGRmX3Rhc2syLCBkZl90YXNrMiR0eG5fZGVzY3JpcHRpb249PSdQQVkvU0FMQVJZJykNCnNhbGFyeTEgPC0gc2FsYXJ5MVssIGMoJ2ZpcnN0X25hbWUnLCAndHhuX2Rlc2NyaXB0aW9uJywgJ2Ftb3VudCcsICdhY2NvdW50JywgJ2FnZScpXQ0Kc2FsYXJ5X3N1bTEgPC0gZGF0YS5mcmFtZSgpDQpzYWxhcnlfc3VtMSA8LSBhZ2dyZWdhdGUoc2FsYXJ5MSRhbW91bnQsIGxpc3QoZmFjdG9yKHNhbGFyeTEkYWNjb3VudCkpLCBzdW0pDQpuYW1lc19hY2NvdW50X2lkczEgPC0gZGF0YS5mcmFtZSgpDQpuYW1lc19hY2NvdW50X2lkczEgPC0gc2FsYXJ5MVtjKCdmaXJzdF9uYW1lJywgJ2FjY291bnQnLCAnYW1vdW50JywgJ2FnZScpXQ0KbmFtZXNfYWNjb3VudF9pZHNfYXJyYW5nZTEgPC0gZGF0YS5mcmFtZSgpDQpuYW1lc19hY2NvdW50X2lkc19hcnJhbmdlMSA8LSBhcnJhbmdlKG5hbWVzX2FjY291bnRfaWRzMSwgbGlzdChmYWN0b3IobmFtZXNfYWNjb3VudF9pZHMxJGFjY291bnQpKSkNCm5hbWVzX2FjY291bnRfaWRzX2FycmFuZ2UxIDwtIGFycmFuZ2UobmFtZXNfYWNjb3VudF9pZHNfYXJyYW5nZTEsIGxpc3QoZmFjdG9yKG5hbWVzX2FjY291bnRfaWRzX2FycmFuZ2UxJGFjY291bnQpKSkNCnN1bV9vZl9zYWxhcmllczEgPC0gZGF0YS5mcmFtZSgpDQpzdW1fb2Zfc2FsYXJpZXMxIDwtIGFnZ3JlZ2F0ZShuYW1lc19hY2NvdW50X2lkc19hcnJhbmdlMSRhbW91bnQsIGxpc3QoZmFjdG9yKG5hbWVzX2FjY291bnRfaWRzX2FycmFuZ2UxJGFjY291bnQpICksIHN1bSkNCmFnZV93aXNlIDwtIGRhdGEuZnJhbWUoKQ0KYWdlX3dpc2UgPC0gd2l0aChuYW1lc19hY2NvdW50X2lkc19hcnJhbmdlMSwgbmFtZXNfYWNjb3VudF9pZHNfYXJyYW5nZTFbb3JkZXIoYWdlLCBhbW91bnQpLF0pDQphZ2Vfd2lzZSA8LSBhZ2dyZWdhdGUoYWdlX3dpc2UkYW1vdW50LCBsaXN0KGZhY3RvcihuYW1lc19hY2NvdW50X2lkc19hcnJhbmdlMSRhZ2UpKSwgc3VtKQ0KYWdlTnVtIDwtIHRhYmxlKGRmX3Rhc2syJGFnZSkNCmFnZU51bV92ZWN0b3IgPC0gYygpDQpmb3IgKGkgaW4gc2VxX2Fsb25nKDE6bGVuZ3RoKGFnZU51bSkpKXsNCiAgYWdlTnVtX3ZlY3RvciA8LSBhcHBlbmQoYWdlTnVtX3ZlY3RvciwgYWdlTnVtW1tpXV0pDQp9DQphZ2Vfd2lzZSQnYWdlX251bScgPC0gYWdlTnVtX3ZlY3Rvcg0KDQp7DQogIHBuZyhmaWxlbmFtZT0iU2FsYXJ5X2FnZV93aXNlLnBuZyIsIHdpZHRoPTEyMDAsIGhlaWdodD01MDApDQogIA0KICAjIyMgZ2dwbG90IGluaXQNCiAgDQogIHBsdCA8LSBnZ3Bsb3QoYWdlX3dpc2UsIGFlcyhHcm91cC4xLCB4KSkNCiAgDQogICMjIyBMYWJlbHMNCiAgDQogIGwgPC0gbGFicyh4PSJBZ2UiLCB5PSJUb3RhbCBTYWxhcnkiLCB0aXRsZT0iU2FsYXJpZXMgQWdlIFdpc2UiKQ0KICANCiAgIyMjIHRoZW1lIHN0YXJ0DQogIA0KICB0PC0gdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEsIHNpemU9MTIsIGZhY2U9ImJvbGQiLCBjb2xvdXIgPSAiYmx1ZSIpLCANCiAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFjZT0gImJvbGQiLCBjb2xvdXI9ICJicm93biIgKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0iYm9sZCIsIGNvbG91ciA9ICJvcmFuZ2UiKSwgICAgDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGZhY2U9ImJvbGQiLCBjb2xvdXIgPSAib3JhbmdlIiksICAgIA0KICAgICNheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJib2xkIiwgY29sb3VyID0gImJsYWNrIiksIA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGZhY2U9ImJvbGQiLCBjb2xvdXIgPSAiYmx1ZSIpKSANCiAgDQogICMjI3RoZW1lIGVuZA0KICANCiAgcHJpbnQocGx0K2dlb21fcG9pbnQoc2l6ZT02LCBzaG93LmxlZ2VuZCA9IFRSVUUpK2wrdCArIGdlb21fbGFiZWxfcmVwZWwoYWVzKGxhYmVsID0gYWdlX3dpc2UkYWdlX251bSksDQogICAgICAgICAgICAgICAgICBib3gucGFkZGluZyAgID0gMSwNCiAgICAgICAgICAgICAgICAgIGxhYmVsLnNpemUgPSAwLjUsDQogICAgICAgICAgICAgICAgICBwb2ludC5wYWRkaW5nID0gMC41LA0KICAgICAgICAgICAgICAgICAgc2VnbWVudC5jb2xvciA9ICdibHVlJykgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9bWVhbihhZ2Vfd2lzZSR4KSwgc2hvdy5sZWdlbmQgPSBUUlVFLCBjb2xvdXI9J2dyZWVuJywgc2l6ZT0xLjUpKQ0KICBkZXYub2ZmKCkNCn0NCg0KYGBgDQoNCmBgYHtyfQ0KIyMjIyBQbG90IG9mIGZpcnN0IDMwIE9ic2VydmF0aW9ucyAjIyMjIyMjIyMjIw0Kew0KICBwbmcoZmlsZW5hbWU9IlN1bV9BZ2VfSW5kaXZpZHVhbC5wbmciLCB3aWR0aD0xNDAwLCBoZWlnaHQ9NjAwKQ0KICBzdW1fYWdlX2luZGl2aWR1YWwgPC0gYWdncmVnYXRlKG5hbWVzX2FjY291bnRfaWRzX2FycmFuZ2UxJGFtb3VudCwgbGlzdChmYWN0b3IobmFtZXNfYWNjb3VudF9pZHNfYXJyYW5nZTEkYWNjb3VudCksIGZhY3RvcihuYW1lc19hY2NvdW50X2lkc19hcnJhbmdlMSRhZ2UpICksIHN1bSkNCiAgdHQ8LSB0aGVtZShheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGZhY2U9ICJib2xkIiwgY29sb3VyPSAiYnJvd24iKSwgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImRhcmsgZ3JlZW4iKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0iYm9sZCIsIGNvbG91ciA9ICJvcmFuZ2UiKSwgICAgDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTQsIGZhY2U9ImJvbGQiLCBjb2xvdXIgPSAib3JhbmdlIiksICAgIA0KICAgICNheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJib2xkIiwgY29sb3VyID0gImJsYWNrIiksIA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGZhY2U9ImJvbGQiLCBjb2xvdXIgPSAiYmx1ZSIpKQ0KICBsQSA8LSBsYWJzKHg9IkFjY291bnRzIiwgeT0iVG90YWwgU2FsYXJ5IiwgdGl0bGU9IlNhbGFyaWVzIGJ5IEluZGl2aWR1YWwgQWdlIikNCiAgcGx0X0EgPC0gZ2dwbG90KHN1bV9hZ2VfaW5kaXZpZHVhbFsxOjQ2LCBdLCBhZXMoR3JvdXAuMSwgeCwgZ3JvdXA9R3JvdXAuMikpDQogIHBsdF9BMSA8LSBwbHRfQSArIGZhY2V0X2dyaWQoLiB+IEdyb3VwLjIpICsgZ2VvbV9wb2ludChzaXplPTIuNSwgY29sPSdyZWQnKSArbEEgKyB0dA0KICBwcmludChwbHRfQTEpDQogIGRldi5vZmYoKQ0KfQ0KDQojIyMjIFBsb3Qgb2YgZmlyc3QgMzEtNjAgT2JzZXJ2YXRpb25zICMjIyMjIyMjIyMjDQp7DQogIHBuZyhmaWxlbmFtZT0iU3VtX0FnZV9JbmRpdmlkdWFsMS5wbmciLCB3aWR0aD0xMjAwLCBoZWlnaHQ9NjAwKQ0KICBsQiA8LSBsYWJzKHg9IkFjY291bnRzIiwgeT0iVG90YWwgU2FsYXJ5IiwgdGl0bGU9IlNhbGFyaWVzIGJ5IEluZGl2aWR1YWwgQWdlIikNCiAgcGx0X0IgPC0gZ2dwbG90KHN1bV9hZ2VfaW5kaXZpZHVhbFs0Nzo3MywgXSwgYWVzKEdyb3VwLjEsIHgsIGdyb3VwPUdyb3VwLjIpKQ0KICBwbHRfQjEgPC0gcGx0X0IgKyBmYWNldF9ncmlkKC4gfiBHcm91cC4yKSArIGdlb21fcG9pbnQoc2l6ZT0yLjUsIGNvbD0ncmVkJykgKyBsQiArIHR0DQogIHByaW50KHBsdF9CMSkNCiAgZGV2Lm9mZigpDQp9DQojIyMjIFBsb3Qgb2YgZmlyc3QgNjEtMTAwIE9ic2VydmF0aW9ucyAjIyMjIyMjIyMjIw0Kew0KICBwbmcoZmlsZW5hbWU9IlN1bV9BZ2VfSW5kaXZpZHVhbDIucG5nIiwgd2lkdGg9MTIwMCwgaGVpZ2h0PTYwMCkNCiAgbEMgPC0gbGFicyh4PSJBY2NvdW50cyIsIHk9IlRvdGFsIFNhbGFyeSIsIHRpdGxlPSJTYWxhcmllcyBieSBJbmRpdmlkdWFsIEFnZSIpDQogIHBsdF9DIDwtIGdncGxvdChzdW1fYWdlX2luZGl2aWR1YWxbNzQ6MTAwLCBdLCBhZXMoR3JvdXAuMSwgeCwgZ3JvdXA9R3JvdXAuMikpDQogIHBsdF9DMSA8LSBwbHRfQyArIGZhY2V0X2dyaWQoLiB+IEdyb3VwLjIpICsgZ2VvbV9wb2ludChzaXplPTIuNSwgY29sPSdyZWQnKSArIGxDICsgdHQNCiAgcHJpbnQocGx0X0MxKQ0KICBkZXYub2ZmKCkNCn0NCg0KYGBgDQoNCmBgYHtyfQ0KbWVhbl9hZ2UgPC0gYWdncmVnYXRlKHN1bV9hZ2VfaW5kaXZpZHVhbCR4LCBsaXN0KGZhY3RvcihzdW1fYWdlX2luZGl2aWR1YWwkR3JvdXAuMikpLCBtZWFuKQ0KbWVhbl9hZ2UgPC0gZGF0YS5mcmFtZShtZWFuX2FnZSkNCm1lYW5fYWdlJEdyb3VwLjEgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobWVhbl9hZ2UkR3JvdXAuMSkpDQpsaW5lYXJfcmVncmVzc2lvbiA8LSBsbSh4IH4gR3JvdXAuMSwgZGF0YSA9IG1lYW5fYWdlKQ0KDQp7DQogIHBuZyhmaWxlbmFtZT0iU2FsYXJpZXNfYnlfYWdlcy5wbmciLCB3aWR0aD0xNDAwLCBoZWlnaHQ9NjAwKQ0KICANCiAgdHRhIDwtIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xLCBzaXplPTEyLCBmYWNlPSJib2xkIiwgY29sb3VyID0gImJsdWUiKSwgDQogICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFjZT0gImJvbGQiLCBjb2xvdXI9ICJicm93biIpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE0LCBmYWNlPSJib2xkIiwgY29sb3VyID0gIm9yYW5nZSIpLCAgICANCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCwgZmFjZT0iYm9sZCIsIGNvbG91ciA9ICJvcmFuZ2UiKSwgICAgDQogICAgI2F4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGZhY2U9ImJvbGQiLCBjb2xvdXIgPSAiYmxhY2siKSwgDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgZmFjZT0iYm9sZCIsIGNvbG91ciA9ICJibHVlIikpDQogIGxBMSA8LSBsYWJzKHg9IkFnZSIsIHk9IlRvdGFsIFNhbGFyeSIsIHRpdGxlPSJTYWxhcmllcyBieSBhZ2VzIikNCiAgcGx0X0FCIDwtIGdncGxvdChtZWFuX2FnZSwgYWVzKHg9R3JvdXAuMSwgeT14KSkgKyBnZW9tX3Ntb290aChmb3JtdWxhPXl+eCwgbWV0aG9kPSdsbScsIHNlPUZBTFNFKQ0KICBwbHRfQUIxIDwtIHBsdF9BQiAgKyBnZW9tX3BvaW50KHNpemU9Mi41LCBjb2w9J3JlZCcsIHNob3cubGVnZW5kID0gVFJVRSkrIHR0YSArIGxBMSArIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDE4LCA3OCwgMSkpDQogIHByaW50KHBsdF9BQjEpDQogIGRldi5vZmYoKQ0KfQ0KcHJpbnQocGx0X0FCMSkNCnByZWRpY3Rpb25zIDwtIHByZWRpY3QobGluZWFyX3JlZ3Jlc3Npb24sIGRhdGEuZnJhbWUoR3JvdXAuMT01MykpDQpwcmVkaWN0aW9ucw0KIyBzdW1tYXJpemUgcmVzdWx0cw0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkoa2xhUikNCiNjb25mdXNpb25NYXRyaXgocHJlZGljdGlvbnMsIGRhdGEuZnJhbWUoR3JvdXAuMT01MykpDQpgYGANCg0K